#include "../LogFile.h"
#include <cassert>
#include <stdio.h>
#include <time.h>
using namespace yhaida;

// std::unique_ptr<MutexLock> _mutex;
// std::unique_ptr<Detail::File> _file;

// const static int kCheckTimeRoll = 1024;
// const static int kRollPerSeconds = 60 * 60 * 24; // "second/day"
LogFile::LogFile(const std::string &baseName, size_t rollSize, const int flushInterval, bool isThreadSafe)
    : _baseName(baseName),
      _rollSize(rollSize),
      _flushInterval(flushInterval),
      _count(0),
      _startOfPeriod(0),
      _lastRoll(0),
      _lastFlush(0),
      _mutex(isThreadSafe ? new MutexLock() : NULL)
{
    assert(baseName.find('/') == std::string::npos);
    //新建
    rollFile();
}
std::string LogFile::getLogFileName(const std::string &baseName, time_t *time)
{
    std::string fullName;
    fullName.reserve(baseName.size() + 32);
    // 1.
    fullName = baseName;

    char t_time[32];
    char t_pid[32];

    struct tm t_tm;
    //获取nowTime
    *time = ::time(NULL);
    gmtime_r(time, &t_tm);
    // 2.
    strftime(t_time, sizeof(t_time), ".%Y%m%d-%H%M%S", &t_tm);
    fullName += t_time;
    // 3.
    snprintf(t_pid, sizeof(t_pid), ".%d", CurrentThread::tid());
    fullName += t_pid;
    // 4.
    fullName += ".log";
    return fullName;
}
void LogFile::rollFile()
{
    time_t nowTime = 0;
    std::string fileName = getLogFileName(_baseName, &nowTime);
    //取整
    time_t start = nowTime / kRollPerSeconds * kRollPerSeconds;
    //每天重新roll一个new文件
    if (nowTime > _lastRoll)
    {
        _lastRoll = nowTime;
        _lastFlush = nowTime;
        _startOfPeriod = start;
        _file.reset(new yhaida::Detail::File(fileName));
    }
}
void LogFile::flush()
{
    if (_mutex)
    {
        MutexLockGuard guard(*_mutex);
        _file->flush();
    }
    else
    {
        _file->flush();
    }
}
void LogFile::write_unlock(const char *str, int length)
{
    _file->append(str, length);

    if (_file->getWriteBytes() > _rollSize)
    {
        rollFile();
    }
    else
    {
        //写入超过一定次数后：
        if (_count > kCheckTimeRoll)
        {
            _count = 0;
            time_t nowTime = 0;
            time_t thisPeriod = nowTime / kRollPerSeconds * kRollPerSeconds;
            // new day
            if (thisPeriod > _startOfPeriod)
            {
                rollFile();
            }
            // this day but pass flushInterval
            else if (nowTime - _lastFlush > _flushInterval)
            {
                _lastFlush = nowTime;
                _file->flush();
            }
        }
        else
        {
            ++_count;
        }
    }
}
void LogFile::write(const char *str, const int length)
{
    if (_mutex)
    {
        MutexLockGuard guard(*_mutex);
        write_unlock(str, length);
    }
    else
    {
        write_unlock(str, length);
    }
}
